#pragma once

#include "TimeSys.h"

namespace ns_Time
{
    class JulianTime : public TimeSys
    {
    public:
        using DayType = long long;
        using SecondType = double;

    public:
        JulianTime()
        {
        }

        JulianTime(DayType day, SecondType second)
            : _day(day),
              _second(second)
        {
        }

        SecondCount SecondFromRefTime() const override
        {
            return static_cast<SecondCount>((_day - GetRefTime()->_day) * DaySecond + _second - GetRefTime()->_second);
        }

        JulianTime *TimeAfterSecond(SecondCount seconds) const override
        {
            int secondsInt;
            double secondsMilli;
            Mathf::SplitDouble(seconds, &secondsInt, &secondsMilli);

            DayType plusDay = secondsInt / DaySecond;
            SecondType newSecond = (secondsInt % DaySecond) + _second;

            if (newSecond > DaySecond)
            {
                plusDay++;
                newSecond -= DaySecond;
            }

            JulianTime *ans = new JulianTime(plusDay, newSecond);
            return ans;
        }

        JulianTime *GetRefTime() const override
        {
            static JulianTime refTime = JulianTime(2444239, 0.5 * DaySecond);
            return &refTime;
        }

        bool Decode(const std::string& inJson) override
        {
            Json::Value inValue;
			Json::Reader reader;
			bool parsingSuccessful = reader.parse(inJson, inValue);
			if (!(parsingSuccessful && inValue["Type"].asString() == "TimeSys"))
				return false;

            SecondCount seconds = inValue["SecondsFromRefTime"].asDouble();

            auto tmp = GetRefTime()->TimeAfterSecond(seconds);
            *this = *tmp;

            return true;
        }

    private:
        DayType _day;
        SecondType _second;
    };
}